Event.h & Event.c

Event 是一种同步原语,用以协调多个任务的执行,管理任务的等待队列(区分于 Task)。

事件类型定义

首先给出头文件中关于 Event 类型(_eEventType)的定义:

typedef enum _eEventType
{
    eEventTypeUnknown               = (0 << 16),    //未定义类型
    eEventTypeSem                 	= (1 << 16),    //信号量类型
    eEventTypeMbox                	= (2 << 16),    //邮箱类型
    eEventTypeMemPool              	= (3 << 16),    //存储块类型
    eEventTypeEventGroup           	= (4 << 16),    //事件标志组
    eEventTypeMutex                 = (5 << 16),    //互斥信号量类型
}eEventType;

typedef struct  _tEvent
{
    eEventType type;

    tList waitList; 
    
}tEvent;

其中每个事件(Event) 是一个由事件类型和事件等待链表组成的结构体,表明了事件类型和事件之间的次序关系。

初始化事件控制快

void vEventInit(tEvent * event, eEventType type)
{
    event->type = type;
    vListInit(&event->waitList);
}

该部分将 event 设置为 type 中的参数。

初始化等待任务(使任务进入等待状态)

void vEventWait(tEvent * event, tTask * task, void * msg, uint32_t state, uint32_t timeout)
{
    /* 进入临界区 */
    uint32_t status = uTaskEnterCritical();

    // task->state = state;
    
    /* 设置任务等待的事件结构 */
    task->waitEvent = event;
    /* 设置任务等待事件的消息存储位置  */
    task->waitEventMsg = msg;
    /* 清空事件的等待结果 */
    task->waitEventResult = eErrorNoError;

    /* 将任务从就绪队列中移除 */
    vTaskRdyListRemove(task);

    /* 将任务插入到等待队列中 */
    vListInsertLast(&event->waitList, &task->linkNode);

    if (timeout)
    {
        tTaskDelayWait(task, timeout);
    }

    /* 退出临界区 */
    vTaskExitCritical(status);
}

用于使当前任务进入等待状态。

首先在临界区中设置任务等待时间的信息,然后从就绪任务队列中删除,插入等待队列。

唤醒等待任务

tTask * tEventWakeUp(tEvent * event, void * msg, uint32_t result)
{
    tTask * task  = (tTask *)0;
    tNode * node;

    uint32_t status = uTaskEnterCritical();

    /* 获取等待队列的第一个节点 */
    if((node = tListRemoveFirst(&event->waitList)) != (tNode *)0)
    {
        /* 获取该节点对应的任务控制块 */
        task = (tTask *)nodeParent(node, tTask, linkNode);

        /* 设置收到的消息、结构,清除相应的等待标志位 */
        task->waitEvent = (tEvent *)0;
        task->waitEventMsg = msg;
        task->waitEventResult = result;

        if(task->delayTicks != 0)
        {
            vTaskDelayWakeUp(task);
        }

        /* 将任务加入就绪队列 */
        vTaskSchedRdy(task);

    }

    vTaskExitCritical(status);

    return task;
}

唤醒等待队列中的第一个任务。

在临界区中获取等待队列的第一个节点,设置任务控制块,然后加入就绪队列。

唤醒指定等待任务

void vEventWakeUpTask(tEvent * event, tTask * task, void *msg, uint32_t result);

从等待队列中删除任务

void vEventRemoveTask(tTask * task, void * msg, uint32_t result)
{
 	 /* 进入临界区 */
    uint32_t status = uTaskEnterCritical();

	/* 将任务从所在的等待队列中移除 */
	vListRemoveNode(&task->waitEvent->waitList, &task->linkNode);

  	/* 设置收到的消息、结构,清除相应的等待标志位 */
    task->waitEvent = (tEvent *)0;
    task->waitEventMsg = msg;
   	task->waitEventResult = result;

	/* 退出临界区 */
    vTaskExitCritical(status);     
}

删除所有等待中的任务

uint32_t uEventRemoveAll(tEvent * event, void * msg, uint32_t result)
{
    uint32_t  count;

    tNode * node ;

 	 /* 进入临界区 */
    uint32_t status = uTaskEnterCritical();    

    count = uGetListNodeCount(&event->waitList);

    while ((node = tListRemoveFirst(&event->waitList)) != (tNode * )0)
    {       
        tTask * task = (tTask *) nodeParent(node, tTask, linkNode);

        /* 设置收到的消息、结构,清除相应的等待标志位 */
        task->waitEvent = (tEvent *)0;
        task->waitEventMsg = msg;
        task->waitEventResult = result;

        if(task->delayTicks != 0)
        {
            vTaskDelayWakeUp(task);
        }

        /* 将任务加入就绪队列 */
        vTaskSchedRdy(task);
    }

	/* 退出临界区 */
    vTaskExitCritical(status);    

    return count; 
}

同时将事件发送给所有任务。

获取等待任务数量

uint32_t uEventGetWaitCount(tEvent * event)
{
    uint32_t count = 0;

    uint32_t status = uTaskEnterCritical();

    count = uGetListNodeCount(&event->waitList);  

    vTaskExitCritical(status);     

    return count;    
}

Last modified: 2026-05-24